package main

import (
	"fmt"
	"io"
	"os"
	"reflect"
	"time"
)

type Point struct {
	X, Y int
}

func main() {
	AnyArgment(reflect.ValueOf("Hello Today"))
	AnyArgment(reflect.ValueOf(-1))
	AnyArgment(reflect.ValueOf(time.Second))
	AnyArgment(reflect.ValueOf(true))
	AnyArgment(reflect.ValueOf([]int{1, 2, 3}))
	m := map[string]int{"A": 65, "T": 84}
	AnyArgment(reflect.ValueOf(m))
	AnyArgment(reflect.ValueOf(make(chan int)))
	AnyArgment(reflect.ValueOf(func() {}))
	p := Point{X: 1, Y: 2}
	AnyArgment(reflect.ValueOf(p))
	var w io.Writer = os.Stdout
	AnyArgment(reflect.ValueOf(w))
}

func AnyArgment(v reflect.Value) {
	switch v.Kind() {
	case reflect.Invalid:
		fmt.Println("invalid")
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		fmt.Printf("v.Int() = %d\n", v.Int())
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		fmt.Printf("v.Uint() = %d\n", v.Uint())
	case reflect.String:
		fmt.Printf("string = %v\n", v.String())
	case reflect.Bool:
		fmt.Printf("v.Bool() = %v\n", v.Bool())
	case reflect.Slice, reflect.Array:
		fmt.Printf("Slice/Array, v.Len()=%d, Value=[", v.Len())
		var i int
		for i = 0; i < v.Len()-1; i++ { //reflect.Value can not be ranged
			fmt.Printf("%v,", v.Index(i))
		}
		fmt.Printf("%v]\n", v.Index(i))
	case reflect.Struct:
		fmt.Printf("Struct, v.Type().String() = %s, field is {", v.Type().String())
		var i int
		for i = 0; i < v.NumField()-1; i++ {
			fmt.Printf("%s :", v.Type().Field(i).Name)
		}
		fmt.Printf("%s}\n", v.Type().Field(i).Name)
	case reflect.Map:
		fmt.Printf("Map, v.Type().String() = %s, key:value is {", v.Type().String())
		for _, key := range v.MapKeys() {
			fmt.Printf("%s:%v,", key, v.MapIndex(key))
		}
		fmt.Printf("}\n")
	case reflect.Interface:
		if v.IsNil() {
			fmt.Println("nil interface")
		} else {
			fmt.Printf("reflect.Interface: %s\n", v.Elem().Type())
		}
	case reflect.Chan, reflect.Func, reflect.Ptr:
		fmt.Printf("v.Pointer() = %x , v.Type().String() = %s\n", v.Pointer(), v.Type().String())
	}
}
